package org.example.maven.museumuser.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.servlet.http.HttpServletRequest;
import org.example.maven.museumuser.domain.entity.ActionTicketUser;
import org.example.maven.museumuser.domain.entity.IdentityName;
import org.example.maven.museumuser.domain.pojo.Result;
import org.example.maven.museumuser.domain.pojo.action.ActionOrder;
import org.example.maven.museumuser.mapper.ActionTicketUserMapper;
import org.example.maven.museumuser.service.IActionTicketService;
import org.example.maven.museumuser.service.IActionTicketUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.maven.museumuser.service.IdentityNameService;
import org.example.maven.museumuser.utils.JwtUtils;
import org.example.maven.museumuser.utils.ThreadlocalUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import static org.example.maven.museumuser.domain.pojo.StaticVariable.Lock_Action_Order_Key;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zafkiel
 * @since 2025-06-22
 */
@Service
public class ActionTicketUserServiceImpl extends ServiceImpl<ActionTicketUserMapper, ActionTicketUser> implements IActionTicketUserService {

    @Autowired
    private IdentityNameService identityNameService;
    @Autowired
    private IActionTicketService iActionTicketService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private HttpServletRequest request;  // 获取请求信息

    //获取当前类的代理对象
    private IActionTicketUserService proxy;

    //获取一个阻塞队列
    private static final BlockingQueue<ActionOrder> blockingQueue = new LinkedBlockingQueue<>();
    //获取一个单核线程池
    private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(1,1,1000, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>());



    //创建一个线程从阻塞队列中取出订单，并执行活动库存扣减操作
    private class ActionOrderThread implements Runnable{
        @Override
        public void run() {
            while (true){
                //从阻塞队列中取出订单
                try {
                    ActionOrder actionOrder = blockingQueue.poll();
                    proxy.deductActionTicket(actionOrder)
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    //获取lua脚本
    private static final DefaultRedisScript<Long> Action_Script;
    static {
        Action_Script = new DefaultRedisScript<>();
        Action_Script.setLocation(new ClassPathResource("ActionTicket.lua"));
        Action_Script.setResultType(Long.class);
    }
    @Override
    @Transactional
    public Result saveActionOrder(ActionOrder actionOrder) {
        String JWT= ThreadlocalUtils.get();
        //执行lua脚本
        Long result = stringRedisTemplate.execute(Action_Script,
                Collections.emptyList(),
                actionOrder.getActionTicketId().toString(),actionOrder.getRelativeIdentity(),actionOrder.getChildrenIdentity());
        int r=result.intValue();
        System.out.println(r);
        if(r!=0){
            if(r==1) return Result.error("活动已报名满");
            if(r==2) return Result.error("大人已购买");
            if(r==3) return Result.error("小孩已购买");
        }
        //将订单放入阻塞队列
        blockingQueue.add(actionOrder);
        //获取当前线程的代理对象
        proxy = (IActionTicketUserService) SpringUtil.getBean(this.getClass());
        return Result.success("活动报名成功")
    }
    //判断是否报过名
    private boolean checkIsOrder(ActionOrder actionOrder){
        return baseMapper.exists(new QueryWrapper<ActionTicketUser>()
                .eq("action_ticket_id",actionOrder.getActionTicketId())
                .and(wrapper -> wrapper
                        .eq("relative_identity", actionOrder.getRelativeIdentity())
                        .or()
                        .eq("children_identity", actionOrder.getChildrenIdentity())
                )
        );
    }

    //执行活动库存扣减操作
    @Override
    public void deductActionTicket(ActionOrder actionOrder){
        //从请求中获取token
        String jwt=request.getHeader("Authorization");
        //从jwt中解析出手机号
        String phone=JwtUtils.getJwtUsername(jwt);
        //获取锁
        RLock lock = redissonClient.getLock(Lock_Action_Order_Key+ phone);
        if(!lock.tryLock()){
            return;
        }
        try{
            //判断是否报过名
            if(checkIsOrder(actionOrder)){
                return;
            }
            //添加身份
            identityNameService.addIdentityByName(new IdentityName(actionOrder.getRelativeIdentity(),actionOrder.getRelativeName()));
            identityNameService.addIdentityByName(new IdentityName(actionOrder.getChildrenIdentity(),actionOrder.getChildrenName()));
            //执行活动库存扣减操作
            if(iActionTicketService.deductActionTicket(actionOrder.getActionTicketId())){
                //扣减成功，添加订单
                ActionTicketUser actionTicketUser= BeanUtil.toBean(actionOrder,ActionTicketUser.class);
                actionTicketUser.setCreateTime(LocalDateTime.now());
                //添加订单
                baseMapper.insert(actionTicketUser);
                //return Result.success("活动报名成功");
            }
        }finally {
            lock.unlock();
        }
    }
}
